#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "vector.h"

void check(bool test) {
	if (!test)
		exit(1);
}

void *thread1(void*);
void *thread2(void*);
void *thread3(void*);
void *thread4(void*);

nbds::vector<int> l;

int main() {
	pthread_t t1, t2, t3, t4;
	
	pthread_create(&t1, NULL, thread1, NULL);
	pthread_create(&t2, NULL, thread2, NULL);
	pthread_create(&t3, NULL, thread3, NULL);
	pthread_create(&t4, NULL, thread4, NULL);

	pthread_join(t2, NULL);
	pthread_join(t4, NULL);
	pthread_join(t1, NULL);
	pthread_join(t3, NULL);

	int vals[10];
	memset(&vals, 0, sizeof(vals));

	nbds::vector<int>::iterator it = l.begin();
	for (int i = 0; i < l.count(); i++) {
		check(*it > 0 && *it < 11);
		vals[*it - 1] ++;
		it++;
	}

	for (int i = 0; i < 10; i++)
		check(vals[i] == 10000);

	exit(0);
}

void *thread1(void*) { 
	for (int i = 0; i < 5000; i++) {
		l.push_back(6);
		for (volatile int i = 0; i < 10; i++) wait();
		l.push_back(7);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.push_back(8);
		for (volatile int i = 0; i < 100; i++) wait();
		l.push_back(9);
		l.push_back(10);
	}
}

void *thread2(void*) {
	for (int i = 0; i < 5000; i++) {
		l.push_back(1);
		for (volatile int i = 0; i < 100; i++) wait();
		l.push_back(2);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.push_back(3);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.push_back(4);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.push_back(5);
	}
}

void *thread3(void*) {
	for (int i = 0; i < 5000; i++) {
		l.push_back(1);
		for (volatile int i = 0; i < 100; i++) wait();
		l.push_back(2);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.push_back(3);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.push_back(4);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.push_back(5);
	}
}

void *thread4(void*) {
	for (int i = 0; i < 5000; i++) {
		l.push_back(6);
		for (volatile int i = 0; i < 10; i++) wait();
		l.push_back(7);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.push_back(8);
		for (volatile int i = 0; i < 100; i++) wait();
		l.push_back(9);
		l.push_back(10);
	}
}

